﻿
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace GameBoxTools
{
    public class StatisticCreate : MonoBehaviour
    {
        private GameObject LineGraph;
        private Transform Series;
        private GameObject Serie;

        private GameObject[] serieArr;
        private int x_num = 0;

        private int rendersCount = 0;//Render组件数量
        private int rtCount = 0;//纹理数量

        //UI
        private RenderCtrl[] RenderCtrlArr;
        private Transform RenderRoot;
        private Transform ScrollView;
        private GameObject RenderObj;
        private Button TitleR;//渲染所有
        private Button TitleS;//显示所有
        private Text tip1;
        private Text tip2;
        private GameObject ToolTips;
        private GameObject RotatePsToggles;
        private Toggle[] R_togglesArr = new Toggle[5];//0,90,180,270,Custom
        private Transform PSRoot;
        private Transform PSGo;//粒子实体
        private bool isReCollect = false;//重新采样
        
        private BaseStatistic bs;
        public bool isOverDraw = true;

        //render颜色
        private Color[] serieColor = new Color[]
        {
            new Color(220/255f, 20/255f, 60/255f), new Color(255/255f,0/255f,255/255f), new Color(148/255f,0/255f,211/255f), new Color(106/255f,90/255f,205/255f), new Color(0/255f,0/255f,255/255f),
            new Color(100/255f,149/255f,237/255f),new Color(70/255f,130/255f,180/255f),new Color(95/255f,158/255f,160/255f),new Color(0/255f,128/255f,128/255f),new Color(0/255f,250/255f,154/255f),
            new Color(0,255/255f,0),new Color(154/255f,205/255f,50/255f),new Color(255/255f,215/255f,0),new Color(184/255f,134/255f,11/255f),new Color(255/255f,165/255f,0),
            new Color(210/255f,105/255f,30/255f),new Color(255/255f,69/255f,0),new Color(240/255f,128/255f,128/255f),new Color(178/255f,34/255f,34/255f),new Color(128/255f,0,0)
        };

        private WMG_List<Vector2>[] showdata;//各Render性能，最后一个存储总数据
        private Dictionary<int, List<List<Area>>> originCacheData = new Dictionary<int, List<List<Area>>>();//缓存粒子每个角度源数据
        private Dictionary<int, Dictionary<int, WMG_List<Vector2>>> resultCacheData = new Dictionary<int, Dictionary<int, WMG_List<Vector2>>>();//缓存粒子每个角度分析结果
        private int currentPSAngleY;//当前粒子y角度
        private int currentShowRendersKey = -1;//当前总体性能
        private List<int> currentShowRenders = new List<int>();//当前总体性能所包含Render

        private void Awake()
        {
            this.LineGraph = this.gameObject;
            this.Series = this.LineGraph.transform.Find("Series");
            this.Serie = this.Series.Find("Serie").gameObject;
            this.RenderRoot = this.LineGraph.transform.Find("RenderCtrl");
            this.ScrollView = this.RenderRoot.Find("Scroll").Find("Viewport").Find("Content").transform;
            this.RenderObj = this.RenderRoot.Find("Render").gameObject;
            this.tip1 = this.RenderRoot.Find("tip1").gameObject.GetComponent<Text>();
            this.tip2 = this.RenderRoot.Find("tip2").gameObject.GetComponent<Text>();
            this.ToolTips = this.RenderRoot.Find("ToolTips").gameObject;
            this.RotatePsToggles = this.RenderRoot.Find("RotatePS").gameObject;
            this.R_togglesArr[0] = this.RotatePsToggles.transform.Find("Toggle0").GetComponent<Toggle>();
            this.R_togglesArr[1] = this.RotatePsToggles.transform.Find("Toggle90").GetComponent<Toggle>();
            this.R_togglesArr[2] = this.RotatePsToggles.transform.Find("Toggle180").GetComponent<Toggle>();
            this.R_togglesArr[3] = this.RotatePsToggles.transform.Find("Toggle270").GetComponent<Toggle>();
			this.R_togglesArr[4] = this.RotatePsToggles.transform.Find("ToggleCus").GetComponent<Toggle>();

            this.TitleR = this.RenderRoot.Find("TitleR").gameObject.GetComponent<Button>();
            this.TitleR.onClick.AddListener(() =>
            {
                this.JustDoIt();
                for (int i = 0; i < this.rendersCount; ++i)
                    this.RenderCtrlArr[i].RenderToggle.isOn = true;
            });

            this.TitleS = this.RenderRoot.Find("TitleS").gameObject.GetComponent<Button>();
            this.TitleS.onClick.AddListener(() =>
            {
                for(int i = 0; i < this.rendersCount; ++i)
                {
                    this.RenderAction(i, 0);
                    this.RenderCtrlArr[i].ShowToggle.isOn = true;
                }
            });

            this.R_togglesArr[0].onValueChanged.AddListener((ison) => { if (ison) { this.RotatePs(0); } });
            this.R_togglesArr[1].onValueChanged.AddListener((ison) => { if (ison) { this.RotatePs(90); } });
            this.R_togglesArr[2].onValueChanged.AddListener((ison) => { if (ison) { this.RotatePs(180); } });
            this.R_togglesArr[3].onValueChanged.AddListener((ison) => { if (ison) { this.RotatePs(270); } });
			this.R_togglesArr[4].onValueChanged.AddListener((ison) => { if (ison) { this.RotatePs(-1); } });

            this.PSRoot = GameObject.Find("PSRoot").transform;
            this.PSGo = this.PSRoot.GetChild(0);
            this.currentPSAngleY = (int)this.PSGo.localEulerAngles.y;

            this.bs = this.PSRoot.GetComponent<BaseStatistic>();
            if (this.isOverDraw)
            {
                this.tip1.text = string.Format("当前粒子角度: {0}，时长: {1}s", this.PSGo.localEulerAngles.ToString(), this.bs.GetCollectTime());
                this.tip2.text = "X：帧数   Y：OverDraw    颜色与各Render对应，白线为总体性能曲线";
            }
            else
            {
                this.tip1.text = string.Format("当前粒子角度: {0}，时长: {1}s", this.PSGo.localEulerAngles.ToString(), this.bs.GetCollectTime());
                this.tip2.text = "X：帧数   Y：透明像素占比    颜色与各Render对应，白线为总体性能曲线";
            }

            this.RotatePsToggles.SetActive(true);
        }

        string[] dot = new string[] {"", ".", "..", "..." };
        int dotindex = 0;
        private void Update()
        {
            if(this.ToolTips.activeInHierarchy)
            {
                ++dotindex;
                this.ToolTips.GetComponent<Text>().text = "数据分析中" + dot[dotindex % 4];
            }
        }

        private void OnDestroy()
        {
            this.originCacheData.Clear();
            this.resultCacheData.Clear();
            this.currentShowRenders.Clear();
        }

        void RotatePs(int angle)
        {
            if(-1 == angle)
            {
                //使用粒子默认旋转进行分析
                this.currentPSAngleY = (int)this.PSGo.localEulerAngles.y;
            }
            else
            {
                this.currentPSAngleY = angle;
                this.PSGo.localEulerAngles = new Vector3(-30, this.currentPSAngleY, 0);
            }
            this.tip1.text = string.Format("当前粒子角度: {0}，时长: {1}s", this.PSGo.localEulerAngles.ToString(), this.bs.GetCollectTime());
            
            //清除之前显示数据
            if (null != this.serieArr)
            {
                foreach (var item in this.serieArr)
                {
                    var wmgs = item.GetComponent<WMG_Series>();
                    bool countChanged = (wmgs.pointValues.Count == 0) ? true : false;
                    wmgs.pointValues.Clear();
                    wmgs.pointValuesListChanged(false, countChanged, false, -1);
                    wmgs.extraXSpace = 2;
                }
            }
            
            if(null != this.RenderCtrlArr)
            {
                foreach (var item in RenderCtrlArr)
                {
                    item.RenderToggle.isOn = true;
                    item.ShowToggle.isOn = false;
                }
            }
            
            if(null != this.showdata)
            {
                foreach (var item in showdata)
                {
                    item.Clear();
                }
            }

            Util.ClearConsole();

            this.RotatePsToggles.SetActive(false);
            this.ToolTips.SetActive(true);
            if(this.resultCacheData.ContainsKey(this.currentPSAngleY))
            {
                this.Init();
				this.bs.SetCameraView();
            }
            else
            {
                this.bs.ReCollect();
            }
        }

        Dictionary<int, WMG_List<Vector2>> GetCacheDic()
        {
            Dictionary<int, WMG_List<Vector2>> cacheData;
            if (!this.resultCacheData.TryGetValue(this.currentPSAngleY, out cacheData))
            {
                cacheData = new Dictionary<int, WMG_List<Vector2>>();
                this.resultCacheData.Add(this.currentPSAngleY, cacheData);
            }

            return cacheData;
        }

        public void AddOriginData(List<Area> framedata)
        {
            List<List<Area>> data;
            if (!this.originCacheData.TryGetValue(this.currentPSAngleY, out data))
            {
                data = new List<List<Area>>();
                this.originCacheData.Add(this.currentPSAngleY, data);
            }

            data.Add(framedata);
        }

        void CreateRenders()
        {
            this.serieArr = new GameObject[this.rendersCount + 1];//最后一个存储总体信息
            for (int i = 0; i < this.serieArr.Length; ++i)
            {
                bool isLast = (i == this.serieArr.Length - 1);//最后一个
                var name = string.Format("Render{0}", i + 1);
                if (isLast) name = "RenderAll";
                GameObject render = Instantiate(this.Serie);
                render.name = name;
                render.SetActive(true);

                var wmgs = render.GetComponent<WMG_Series>();
                wmgs.pointPrefab = isLast ? 0 : i % 3;//结点类型，共3种
                wmgs.seriesName = name;
                wmgs.pointColor = isLast ? new Color(1, 1, 1, 1) : this.serieColor[i % 20];//20种颜色
                wmgs.lineColor = isLast ? new Color(1, 1, 1, 1) : this.serieColor[i % 20];//20种颜色

                wmgs.pointValues.SetList(this.showdata[i]);
                wmgs.pointValuesListChanged(false, true, false, -1);
                wmgs.extraXSpace = 2;

                render.transform.SetParent(this.Series);
                this.serieArr[i] = render;
            }

            this.RenderCtrlArr = new RenderCtrl[this.rendersCount];
            for(int i = 0; i < this.rendersCount; ++i)
            {
                this.RenderCtrlArr[i] = new RenderCtrl(this.RenderObj, this.ScrollView, i, this.bs.wrong_material[i], ClickAction, RenderAction);
            }

            this.ToolTips.transform.SetAsLastSibling();
        }

        /// <summary>
        /// 点击选中回调
        /// </summary>
        /// <param name="index">Render索引</param>
        void ClickAction(int index)
        {
            this.bs.ChooseObj(index);
        }

        /// <summary>
        /// 显示回调
        /// </summary>
        /// <param name="index">Render索引</param>
        /// <param name="type">0渲染并显示 1只渲染不显示 2不渲染不显示</param>
        void RenderAction(int index, int type)
        {
            if (0 == type)
            {
                this.bs.ShowOrHide(index, true);

                //各自
                if (0 == this.showdata[index].Count)
                {
                    var renders = new int[1];
                    renders[0] = index;
                    this.AnalyzeData(index, renders, this.GetCacheDic());
                }
                else
                {
                    var wmgs = this.serieArr[index].GetComponent<WMG_Series>();
                    bool countChanged = (wmgs.pointValues.Count == 0) ? true : false;
                    wmgs.pointValues.SetList(this.showdata[index]);
                    wmgs.pointValuesListChanged(false, countChanged, false, -1);
                    wmgs.extraXSpace = 2;
                }

                //总体
                if(!this.currentShowRenders.Contains(index))
                {
                    this.currentShowRendersKey = -1;
                    this.currentShowRenders.Add(index);
                    foreach(var render in this.currentShowRenders)
                    {
                        this.currentShowRendersKey += (1 << render);
                    }

                    WMG_List<Vector2> data;
                    if(this.GetCacheDic().TryGetValue(this.currentShowRendersKey, out data))
                    {
                        var wmgs = this.serieArr[this.rendersCount].GetComponent<WMG_Series>();
                        bool countChanged = (wmgs.pointValues.Count == 0) ? true : false;
                        wmgs.pointValues.SetList(data);
                        wmgs.pointValuesListChanged(false, countChanged, false, -1);
                        wmgs.extraXSpace = 2;
                    } 
                    else
                    {
                        this.AnalyzeData(this.rendersCount, this.currentShowRenders.ToArray(), this.GetCacheDic());
                    }
                }
            }
            else if(1 == type)
            {
                this.bs.ShowOrHide(index, true);

                var wmgs = this.serieArr[index].GetComponent<WMG_Series>();
                bool countChanged = (wmgs.pointValues.Count == 0) ? true : false;
                wmgs.pointValues.Clear();
                wmgs.pointValuesListChanged(false, countChanged, false, -1);
                wmgs.extraXSpace = 2;

                //总体
                if (!this.currentShowRenders.Contains(index))
                {
                    this.currentShowRendersKey = -1;
                    this.currentShowRenders.Add(index);
                    foreach (var render in this.currentShowRenders)
                    {
                        this.currentShowRendersKey += (1 << render);
                    }

                    WMG_List<Vector2> data;
                    if (this.GetCacheDic().TryGetValue(this.currentShowRendersKey, out data))
                    {
                        wmgs = this.serieArr[this.rendersCount].GetComponent<WMG_Series>();
                        countChanged = (wmgs.pointValues.Count == 0) ? true : false;
                        wmgs.pointValues.SetList(data);
                        wmgs.pointValuesListChanged(false, countChanged, false, -1);
                        wmgs.extraXSpace = 2;
                    }
                    else
                    {
                        this.AnalyzeData(this.rendersCount, this.currentShowRenders.ToArray(), this.GetCacheDic());
                    }
                }
            }
            else
            {
                this.bs.ShowOrHide(index, false);

                var wmgs = this.serieArr[index].GetComponent<WMG_Series>();
                bool countChanged = (wmgs.pointValues.Count == 0) ? true : false;
                wmgs.pointValues.Clear();
                wmgs.pointValuesListChanged(false, countChanged, false, -1);
                wmgs.extraXSpace = 2;

                //总体
                if (this.currentShowRenders.Contains(index))
                {
                    this.currentShowRendersKey = -1;
                    this.currentShowRenders.Remove(index);
                    foreach (var render in this.currentShowRenders)
                    {
                        this.currentShowRendersKey += (1 << render);
                    }

                    WMG_List<Vector2> data;
                    if (this.GetCacheDic().TryGetValue(this.currentShowRendersKey, out data))
                    {
                        wmgs = this.serieArr[this.rendersCount].GetComponent<WMG_Series>();
                        countChanged = (wmgs.pointValues.Count == 0) ? true : false;
                        wmgs.pointValues.SetList(data);
                        wmgs.pointValuesListChanged(false, countChanged, false, -1);
                        wmgs.extraXSpace = 2;
                    }
                    else
                    {
                        this.AnalyzeData(this.rendersCount, this.currentShowRenders.ToArray(), this.GetCacheDic());
                    }
                }
            }
        }

        void SetxAxisData()
        {
            var wmgAG = this.LineGraph.GetComponent<WMG_Axis_Graph>();
            wmgAG.lineSeries = new List<GameObject>(this.serieArr);

            //x轴，帧数
            wmgAG.xAxis.AxisMinValue = 1;
            wmgAG.xAxis.AxisMaxValue = this.x_num;
            WMG_List<string> x_axisLabels = new WMG_List<string>();
            
            if(this.x_num > 20 && this.x_num <= 40)
            {
                for (int i = 1; i <= this.x_num; ++i)
                {
                    x_axisLabels.Add("" + i);
                }
                wmgAG.xAxis.AxisNumTicks = this.x_num;
                wmgAG.xAxis.AxisLabelSize = 20;
                int interval = this.x_num / 20;
                wmgAG.xAxis.AxisLabelSkipInterval = 3 * interval;
            }
            else
            {
                x_axisLabels.Add("1");
                x_axisLabels.Add("" + this.x_num / 2);
                x_axisLabels.Add("" + this.x_num);

                wmgAG.xAxis.AxisNumTicks = 3;
                wmgAG.xAxis.AxisLabelSize = 20;
            }
            wmgAG.xAxis.axisLabels.Clear();
            wmgAG.xAxis.axisLabels.SetList(x_axisLabels);
			
			wmgAG.WMG_Click -= WMG_Click_H;//clear
            wmgAG.WMG_Click += WMG_Click_H;
        }
        
        void WMG_Click_H(WMG_Series aSeries, WMG_Node aNode)
        {
            if ("RenderAll" == aSeries.name)
            {
                var value = aSeries.getNodeValue(aNode);
                this.bs.SimulateParticlesForDeltaTime((int)value.x);
            }
        }

        void SetyAxisData(float max_value)
        {
            var wmgAG = this.LineGraph.GetComponent<WMG_Axis_Graph>();

            //y轴，overdraw
            float y_max = 12.0f;
            int tick_num = 4;
            if (!this.isOverDraw)
            {
                //透明占比最高1.0
                y_max = 1.0f;
                tick_num = 1;
            }
            else
            {
                if(max_value > 12)
                {
                    y_max = max_value;
                    tick_num = 3;
                }
            }
            wmgAG.yAxis.AxisMinValue = 0;
            wmgAG.yAxis.AxisMaxValue = y_max;
            wmgAG.yAxis.AxisNumTicks = tick_num;
            WMG_List<string> y_axisLabels = new WMG_List<string>();
            if (!this.isOverDraw)
            {
                for (int i = 0; i < tick_num; ++i)
                {
                    y_axisLabels.Add("" + i);
                }
            }
            else
            {
                if (y_max > 12)
                {
                    y_axisLabels.Add("1");
                    y_axisLabels.Add("" + y_max / 2);
                    y_axisLabels.Add("" + y_max);
                }
                else
                {
                    for (int i = 0; i < tick_num; ++i)
                    {
                        y_axisLabels.Add("" + i * 3);
                    }
                }
            }
            
            wmgAG.yAxis.axisLabels.Clear();
            wmgAG.yAxis.axisLabels.SetList(y_axisLabels);

            wmgAG.CreateGraph();
        }

        public void Init(int rc = 0, int cc = 0)
        {
            this.tip1.text = string.Format("当前粒子角度: {0}，时长: {1}s", this.PSGo.localEulerAngles.ToString(), this.bs.GetCollectTime());

            if (!this.isReCollect)//曲线按钮等数据，和粒子Y角度无关，相同粒子不会改变，所以只需生成一次即可
            {
                this.rendersCount = rc;
                this.rtCount = cc;

                showdata = new WMG_List<Vector2>[this.rendersCount + 1];//最后一个存储总数据
                for (int i = 0; i < showdata.Length; ++i)
                {
                    showdata[i] = new WMG_List<Vector2>();
                }

                this.CreateRenders();
				this.isReCollect = true;
            }

            //采集帧有可能变化
            if(this.x_num != this.originCacheData[this.currentPSAngleY].Count)
            {
                this.x_num = this.originCacheData[this.currentPSAngleY].Count;
                this.SetxAxisData();
            }

            this.JustDoIt();
            this.RotatePsToggles.SetActive(true);
            this.ToolTips.SetActive(false);
        }

        void JustDoIt()
        {
            this.currentShowRenders.Clear();
            this.currentShowRendersKey = -1;
            for (int i = 0; i < this.rendersCount; ++i)
            {
                this.currentShowRenders.Add(i);
                this.currentShowRendersKey += (1 << i);
            }

            WMG_List<Vector2> data; 
            if (this.GetCacheDic().TryGetValue(this.currentShowRendersKey, out data))
            {
                showdata[this.rendersCount].Clear();
                showdata[this.rendersCount].SetList(data);
                var wmgs = this.serieArr[this.rendersCount].GetComponent<WMG_Series>();
                bool countChanged = (wmgs.pointValues.Count == 0) ? true : false;

                wmgs.pointValues.SetList(showdata[this.rendersCount]);
                wmgs.pointValuesListChanged(false, countChanged, false, -1);
                wmgs.extraXSpace = 2;
            }
            else
            {
                this.AnalyzeData(this.rendersCount, this.currentShowRenders.ToArray(), this.GetCacheDic());
            }

            //设置y轴数据
            float max = 0f;
            foreach(var v in showdata[this.rendersCount])
            {
                if (v.y > max) max = v.y;
            }
            this.SetyAxisData(max);
        }

        void AnalyzeData(int index, int[] renders, Dictionary<int, WMG_List<Vector2>> cacheData)
        {
            int frame = 0;
            Util.ShowProgress(this.originCacheData[this.currentPSAngleY].Count, frame);
            if (index == this.rendersCount)
            {   
                //总体性能原数据清理
                showdata[index].Clear();
            }

            if (0 != renders.Length)
            {
                foreach (var list in this.originCacheData[this.currentPSAngleY])
                {
                    float result = 0f;
                    if(this.isOverDraw)
                        result = Util.calcOverdraw(list, renders, this.rtCount);
                    else
                        result = Util.calcTransparent(list, renders, this.rtCount);

                    ++frame;
                    showdata[index].Add(new Vector2(frame, result));
                    Util.ShowProgress(this.originCacheData[this.currentPSAngleY].Count, frame);
                }

                if (index == this.rendersCount)
                {
                    //总体性能数据进行缓存
                    WMG_List<Vector2> data;
                    if(!cacheData.TryGetValue(this.currentShowRendersKey, out data))
                    {
                        data = new WMG_List<Vector2>();
                        data.SetList(showdata[index]);
                        cacheData.Add(this.currentShowRendersKey, data);
                    }
                }
            }

            var wmgs = this.serieArr[index].GetComponent<WMG_Series>();
            bool countChanged = (wmgs.pointValues.Count == 0) ? true : false;
              
            wmgs.pointValues.SetList(showdata[index]);
            wmgs.pointValuesListChanged(false, countChanged, false, -1);
            wmgs.extraXSpace = 2;
            
            Util.CloseProgress();
        }
    }
}